<?php
/**
 * This file is part of Hyperf Mall.
 *
 * @link     https://gitee.com/scwlkj/hyperf_mall
 * @contact  hyperf_mall@163.com
 */

declare(strict_types=1);

namespace App\Repository;

use App\Constants\CouponConstants;
use App\Exception\BaseException;
use App\Model\CouponModel;
use App\Service\Goods\CateService;
use App\Service\Goods\GoodsService;
use App\Utils\DB;
use App\Utils\Log;
use Hyperf\Di\Annotation\Inject;

class CouponRepository extends BaseRepository
{
    /**
     * @Inject
     * @var CouponModel
     */
    protected $model;

    /**
     * @Inject
     * @var CouponGoodsRepository
     */
    protected CouponGoodsRepository $couponGoodsRepository;

    /**
     * @Inject
     * @var CateService
     */
    protected CateService $cateService;

    /**
     * @Inject
     * @var GoodsService
     */
    protected GoodsService $goodsService;

    /**
     * Notes: A端 - 添加优惠券活动
     * Author: Bruce.z
     * DateTime: 2022/9/6 9:20
     * @param $data
     * @return bool
     * @throws BaseException
     */
    public function baseAdd($data): bool
    {
        $data = $this->checkData($data);

        $_category = [];
        if ($data['goods_type'] == CouponConstants::COUPON_GOODS_TYPE_CATEGORY) {
            foreach ($data['cateTree'] as $k){
                $_category = array_filter(array_merge($_category, $k));
            }
        }
        DB::beginTransaction();
        try {
            $re = parent::baseAdd($data);

            if ($data['goods_type'] == CouponConstants::COUPON_GOODS_TYPE_CATEGORY) {
                $coupon_id = $re['id'];
                $coupon_goods = [];
                foreach ($_category as $key => $value) {
                    $coupon_goods[] =[
                        'coupon_id' => $coupon_id,
                        'params_id' => $value,
                        'type' => 1,
                        'saas_id'=>get_saas_id(),
                        'create_time' => time(),
                        'update_time' => time(),
                    ];
                }

                $this->couponGoodsRepository->batchAdd($coupon_goods);
            }

            DB::commit();
        }catch (\Exception $e){
            DB::rollBack();
            Log::getInstance()->error('添加优惠券失败'.$e->getMessage());
            return false;
        }

        return true;
    }

    /**
     * Notes: 基本检测
     * Author: Bruce.z
     * DateTime: 2022/9/6 9:07
     * @param array $data
     * @return array
     * @throws BaseException
     */
    public function checkData(array $data): array
    {
        //满减券 数据处理
        if ($data['free_type'] == CouponConstants::COUPON_TYPE_REDUCTION) {
            //固定金额跟多级优惠处理
            if ($data['price_type'] == CouponConstants::COUPON_PRICE_TYPE_PRICE && ($data['coupon_price'] > $data['price'])) {
                throw new BaseException(BaseException::BASE_ERROR, '门槛金额要大于优惠券面额');
            }
        }

        //公共时间处理
        if ($data['end_time'] < $data['start_time']) {
            throw new BaseException(BaseException::BASE_ERROR, '开始时间不能大于结束时间');
        }

        if ((empty($data['receive_end_time']) || empty($data['receive_start_time'])) && empty($data['receive_after_day'])) {
            throw new BaseException(BaseException::BASE_ERROR, '券使用时间不能为空');
        }
        if (!empty($data['end_time']) && !empty($data['receive_end_time']) && ($data['end_time'] > $data['receive_end_time'])) {
            throw new BaseException(BaseException::BASE_ERROR, '领取结束时间，必须小于券使用有效期');
        }
        if ((!empty($data['receive_end_time']) && !empty($data['receive_start_time'])) && !empty($data['receive_after_day'])) {
            throw new BaseException(BaseException::BASE_ERROR, '领取时间仅能填写一项');
        }

        $data['residue_num'] = $data['num'];

        return $data;
    }

    /**
     * Notes: 更新活动状态
     * Author: Bruce.z
     * DateTime: 2022/9/6 11:04
     * @param array $ids
     * @param int $status
     * @return bool
     */
    public function updateStatus(array $ids, int $status): bool
    {
        return $this->updateByConditions(['id'=>$ids], ['status'=>$status]);
    }

    /**
     * Notes: 获取详情
     * Author: Bruce.z
     * DateTime: 2022/9/6 11:55
     * @param int $id
     * @return array
     */
    public function detail(int $id): array
    {
        $coupon = $this->getOne(['id'=>$id]);
        if(empty($coupon))return [];

        $type_name = [];
        //分类
        if ($coupon['goods_type'] == CouponConstants::COUPON_GOODS_TYPE_CATEGORY) {
            $category = $this->getCategory($id, $type = 1);
            if ($category) {
                $coupon['category_ids'] = $ids = array_column($category, 'params_id');
                /*$type_name =  $this->cateService->getRows(['id'=>$ids],['id','name']);
                foreach ($type_name as $key => $value) {
                    $categoryIds = $this->cateService->getCategoryIds($value['id']);
                    $type_name[$key]['categoryIds'] = empty($categoryIds) ? [] : $categoryIds;
                }
                $coupon['type_name'] = $type_name;*/
            }
        }

        switch ($coupon['goods_type']){
            case CouponConstants::COUPON_GOODS_TYPE_ALL : //全平台
                $coupon['goods_type_desc'] = '全平台可用';
                break;
            case CouponConstants::COUPON_GOODS_TYPE_CATEGORY : //满折
                $coupon['goods_type_desc'] = '指定分类可用';
                break;
            default : $coupon['goods_type_desc'] = '';
        }

        if ($coupon['time_type'] == CouponConstants::COUPON_USE_TIME_FIX) {
            $coupon['use_time'] = $coupon['receive_start_time'] . '-' .$coupon['receive_end_time'];
        } elseif ($coupon['time_type'] == CouponConstants::COUPON_USE_TIME_DAY) {
            $coupon['use_time'] = '领取后' . $coupon['receive_after_day'] . '天';
        }
        $coupon['free_type_desc'] = CouponConstants::$freeType[$coupon['free_type']];
        if ($coupon['time_type'] == 1) {
            $coupon['receive_start_time'] = '';
            $coupon['receive_end_time'] = '';
        }

        return $coupon;
    }

    /**
     * Notes: 获取指定分类
     * Author: Bruce.z
     * DateTime: 2022/9/6 11:20
     * @param $coupon_id
     * @param $type
     * @return array
     */
    public function getCategory($coupon_id, $type): array
    {
        return $this->couponGoodsRepository->getRows(['coupon_id'=>$coupon_id,'type'=>$type],['coupon_id','params_id']);
    }

    /** 领券中心 列表
     * Notes:
     * Author: Bruce.z
     * DateTime: 2022/9/7 16:42
     * @param int $page
     * @param int $size
     * @return array
     */
    public function appIndex(int $page, int $size):array
    {
        $field = ['name','free_type','goods_type','coupon_price','price','residue_num','id'];
        $_condition = [
            'status'=>CouponConstants::COUPON_ENABLE,
            ['start_time','<', time()],
            ['end_time','>', time()]
        ];

        $data =  $this->getPageRows($_condition, $field,$page, $size);

        if($data['total'] > 0){
            $ids = array_column($data['data'],'id');
            $goods = $this->getGoods($ids);

            foreach ($data['data'] as &$re){
                $re['goods'] = $goods[$re['id']]??[];
            }
        }

        return $data;
    }

    /**
     * Notes: 获取优惠券适用商品
     * Author: Bruce.z
     * DateTime: 2022/9/8 9:38
     * @param array $ids
     * @return array
     */
    private function getGoods(array $ids): array
    {
        $res = $this->goodsService->index(['status'=>CouponConstants::COUPON_ENABLE],['id','img','name','retail_price'],1,3);
        $common_goods = $res['data'];

        $data = [];
        foreach ($ids as $id){
            $cate = $this->couponGoodsRepository->getRows(['coupon_id'=>$id],['params_id']);
            if(empty($cate)){
                $data[$id] = $common_goods;
            }else{
                $cate = array_column($cate, 'params_id');

                $res = $this->goodsService->index(['status'=>CouponConstants::COUPON_ENABLE,'category_id'=>$cate],['id','img','name','retail_price'],1,3);
                $data[$id] = $res['data'];
            }
        }

        return $data;
    }

    public function receiveCoupon($coupon_id, $num = 1): int
    {
        return $this->_searchFactor(['id'=>$coupon_id])->decrement('residue_num', $num);
    }
}
